package com.yanjue.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yanjue.client.BookClient;
import com.yanjue.common.constant.CategoryConstant;
import com.yanjue.common.entity.Book;
import com.yanjue.common.entity.IndexBooklist;
import com.yanjue.common.entity.IndexBooklistItem;
import com.yanjue.common.enums.BookSerialStatusEnum;
import com.yanjue.common.redisKey.RedisHomepageKey;
import com.yanjue.common.redisKey.RedisService;
import com.yanjue.common.util.Result;
import com.yanjue.common.util.ResultUtil;
import com.yanjue.mapper.IndexBooklistItemMapper;
import com.yanjue.mapper.IndexPageConfigMapper;
import com.yanjue.service.IndexBooklistItemService;
import com.yanjue.service.IndexBooklistService;
import com.yanjue.vo.BooklistBookVO;
import com.yanjue.vo.IndexBooklistVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
* @author yanju
* @description 针对表【index_booklist_item(精品页-书单明细)】的数据库操作Service实现
* @createDate 2025-01-16 12:33:44
*/
@Service
public class IndexBooklistItemServiceImpl extends ServiceImpl<IndexBooklistItemMapper, IndexBooklistItem>
    implements IndexBooklistItemService {

    private static final Logger LOGGER = LoggerFactory.getLogger(IndexBooklistItemServiceImpl.class);


    @Autowired
    private RedisService redisService;
    @Autowired
    private IndexPageConfigMapper indexBooklistItemMapper;
    @Autowired
    private IndexBooklistService indexBooklistService;
    @Autowired
    private BookClient bookClient;

    /**
     * 顺序获取书单图书
     * @param booklistId            书单ID
     * @param bookIds               图书IDs
     * @param showNumber            显示数量
     * @param showLikeCount         显示喜欢数
     * @return
     */
    @Override
    public List<BooklistBookVO> getBooklistOrderBooks(Integer booklistId, String bookIds, Integer showNumber, Boolean showLikeCount) {
        //1.顺序，直接顺序往下走就行
        String[] bookIdArray = bookIds.split(",");

        return this.getBooklistBookVOByBookIdArray(bookIdArray, showNumber, showLikeCount);
    }

    /**
     * 获取书单里图书VO --- 根据bookIDs集合获取 booklistBookVO
     * @param bookIdArray 书id集合
     * @param showNumber 榜单展示数量
     * @param showLikeCount 是否展示喜欢数
     * @return
     */
    private List<BooklistBookVO> getBooklistBookVOByBookIdArray(String[] bookIdArray, Integer showNumber, Boolean showLikeCount) {
        List<BooklistBookVO> vos = new ArrayList<>();
        for (String bookId : bookIdArray) {
            //根据bookId获取bookVO
           BooklistBookVO vo = this.getBookVO(bookId);
            if (vo != null){
                //获取喜欢数
                if (showLikeCount){
                    // TODO 获取喜欢数，表结构设计不合理，
                    // TODO 可以给图书加一个喜欢数字段（类似点赞字段）设计一个点赞接口
                    //TODO 只能远程调用account，获取likeSee表 select count(*) from - where bookId = ?

                }
            }
            if (vos.size() == showNumber){
                break;
            }
            vos.add(vo);
        }
        return vos;
    }

    /**
     *根据 bookId 获取 booklistBookVO
     * @param bookId 书id
     * @return 书单里书的vo给前端
     */
    public BooklistBookVO getBookVO(String bookId) {
        //1.先判断有没有对应 id 的 book 数据，调用图书服务 TODO（设计openfeign）
        Book book = bookClient.getBookById(bookId).getData();
        //Book book = bookMapper.selectById(bookId);
        if (book == null){
            LOGGER.warn("book为空，此id对应书不存在Book:{}",book);
            return null;
        }
        BooklistBookVO vo = new BooklistBookVO();
        BeanUtils.copyProperties(book,vo);
        //设置 分类和连载状态具体名字
        vo.setCategoryName(CategoryConstant.categorys.get(book.getDicCategory()) );
        vo.setSerialStatusName(BookSerialStatusEnum.fromValue(book.getDicSerialStatus()).getName());

        return vo;

    }

    /**
     * 书单换一换
     * @param booklistId 书单id
     * @param clientRandomNumber 客户端随机编号
     * @return
     */
    @Override
    public Result getBooklistExchange(Integer booklistId, Integer clientRandomNumber) {
        //1.根据书单id查书单对象
        IndexBooklist booklist = this.indexBooklistService.getIndexBooklistById(booklistId);
        if (booklist == null){
            return ResultUtil.notFound().buildMessage("找不到此书单");
        }
        //2.获取随机书单
        IndexBooklistVO randomIndexBooklistVO = this.indexBooklistService.getRandomIndexBooklistVO(booklist, clientRandomNumber);

        return ResultUtil.success(randomIndexBooklistVO);
    }

    /**
     * 随机获取书单图书信息 BooklistBookVO
     *      1.得到客户端随机编码的book
     *      2.随机获取榜单图书，排除客户端当前的book
     *      3.随机图书列表包括不能重复图书
     * @param booklistId            书单ID
     * @param bookIds               图书IDs
     * @param showNumber            显示数量
     * @param clientRandomNumber    客户端当前随机编号 （不随机就是null）
     * @return 书单里图书集合
     */
    @Override
    public List<BooklistBookVO> getBooklistRandomBooks(Integer booklistId, String bookIds, Integer showNumber, Integer clientRandomNumber, Boolean showLikeCount) {
        //1.获取随机书单
        Set<String> randomBooks = new HashSet<>();
        String[] bookIdArray = bookIds.split(",");
        if (bookIdArray.length < showNumber){
            // 若数据库中不够随机，直接返回顺序书单
            return this.getBooklistOrderBooks(booklistId, bookIds, showNumber, showLikeCount);
        }
        //2.获取客户端展示的书单 clientRandomNumber == null (第一次获取精品页)
        Set<String> clientBookIds = this.getClientBookIds(booklistId,clientRandomNumber);
        Random random = new Random();
        //3.给书单里加书ID，直到加满
        while (randomBooks.size() < showNumber){
            //随机获取并排重
            int randomIndex = random.nextInt(bookIdArray.length);
            String bookId = bookIdArray[randomIndex];
            if (!clientBookIds.contains(bookId) && !randomBooks.contains(bookId)){
                randomBooks.add(bookId);
            }
        }
        String[] randomBooksArray = (String[]) randomBooks.toArray();

        //将随机bookId数组转换成对应的booklistBookVO对象返回
        return this.getBooklistBookVOByBookIdArray(randomBooksArray,showNumber,showLikeCount);

    }



    /**
     * 获取客户端书单ID集合
     * @param booklistId 书单id
     * @param clientRandomNumber 客户端随机编号
     * @return 客户端id集合set
     */
    private Set<String> getClientBookIds(Integer booklistId, Integer clientRandomNumber) {
        if (clientRandomNumber == null){
            //说明不随机
            return new HashSet<>();
        }
        //客户端当前显示书单
        String key = RedisHomepageKey.getBooklistRandomVoKey(booklistId);
        IndexBooklistVO indexBooklistVO = null;
        List<BooklistBookVO> clientBooks = null;
        //从缓存中获取
        try {
            indexBooklistVO = redisService.getHashVal(key,clientRandomNumber.toString(),IndexBooklistVO.class);
            if (indexBooklistVO != null){
                clientBooks = indexBooklistVO.getBooks();
            }
        } catch (Exception e) {
            LOGGER.error("Redis获取客户端书单失败！ex:{},booklistId:{},clientRandomNumber:{}", e, booklistId, clientRandomNumber);
        }
        if (clientBooks == null){
            clientBooks = new ArrayList<>();
        }
        //改成stream流
        //return new HashSet(clientBooks);
        return clientBooks.stream()
                .map(BooklistBookVO::getBookId)
                .collect(Collectors.toSet());
    }


    /*@Override
    public Result getBooklistPagingBooks(Integer booklistId, Integer page, Integer limit) {

        String key = RedisHomepageKey.getBooklistItemPagingKey(booklistId);
        // 使用页码+数量作为Hash的key，防止不同数量的分页页码冲突
        String field = page.toString() + limit;
        List<BooklistBookVO> list = this.redisService.getHashListVal(key, field, BooklistBookVO.class);
        if (CommonUtil.isEmpty(list)) {
            list = new ArrayList<>();
            PageHelper.startPage(page, limit);
            Page<IndexBooklistItem> pageList = (Page<IndexBooklistItem>) this.indexBooklistItemMapper.findPageWithResult(booklistId);
            for (int i = 0; i < pageList.size(); i++) {
                String bookId = pageList.get(i).getBookId();
                BooklistBookVO vo = this.getBookVO(bookId);
                if (vo != null) {
                    list.add(vo);
                }
            }

            if (list.size() > 0) {
                this.redisService.setHashValExpire(key, field, list, RedisExpire.HOUR_TWO);
            }
        }
        return ResultUtil.success(list);
    }*/

}




